﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package Classes {
    import flash.geom.*;
    import Engine.Helpers.*;
    import __AS3__.vec.*;
    import Engine.*;

    public class TerritoryMap {

        protected var m_gridDelta:int;
        protected var m_cells:Array;				// 二维数组，表示地图上哪些格子已经被占用了
        protected var m_boundingRect:Rectangle;	// 整个二维数组格子的地图的边界
        protected var m_occupiedBoundingRect:Rectangle;	// 已经被占用区域的边界
        protected var m_occupiedRects:Vector.<Rectangle>;	// 被占用的区域的集合
        protected var m_surroundingCellOffsets:Array;		// 一个格子上线左右四个格子的便宜量

        public function TerritoryMap(_arg1:int){
            this.m_surroundingCellOffsets = [new Point(0, -1), new Point(-1, 0), new Point(1, 0), new Point(0, 1)];
            super();
            this.m_gridDelta = _arg1;
            this.m_boundingRect = new Rectangle(0, 0, 0, 0);
            this.m_occupiedBoundingRect = new Rectangle(0, 0, 0, 0);
            this.m_cells = new Array();
            this.m_occupiedRects = new Vector.<Rectangle>();
        }
        public function get occupiedBoundingRect():Rectangle{
            return (this.m_occupiedBoundingRect);
        }
        public function addTerritory(_arg1:Rectangle):void{
            var _local12:Rectangle;
            var _local13:int;
            var _local2:int;
			
			// 把_arg1这个矩形放到占用的地图上
            while (_local2 < this.m_occupiedRects.length) {
                _local12 = this.m_occupiedRects[_local2];
                if (_local12.containsRect(_arg1)){
                    return;
                };
                if (_arg1.containsRect(_local12)){
                    this.m_occupiedRects.splice(_local2, 1);
                    _local2--;
                };
                _local2++;
            };
            this.m_occupiedRects.push(_arg1);
			
			// 把_arg1对应的cell标成已经1
            var _local3:int = (_arg1.x / this.m_gridDelta);
            var _local4:int = (_arg1.y / this.m_gridDelta);
            var _local5:int = (_arg1.width / this.m_gridDelta);
            var _local6:int = (_arg1.height / this.m_gridDelta);
            var _local7:int = _local3;
			
            while (_local7 < (_local3 + _local5)) {
                if (this.m_cells[_local7] == null){
                    this.m_cells[_local7] = new Array();
                };
                _local13 = _local4;
                while (_local13 < (_local4 + _local6)) {
                    this.m_cells[_local7][_local13] = 1;
                    _local13++;
                };
                _local7++;
            };
			
			
			// 重新计算占用区域的边界
            var _local8:int = Math.min(_local3, (this.m_boundingRect.x + 1));
            var _local9:int = Math.max(((_local3 + _local5) - 1), (this.m_boundingRect.right - 2));
            var _local10:int = Math.min(_local4, (this.m_boundingRect.y + 1));
            var _local11:int = Math.max(((_local4 + _local6) - 1), (this.m_boundingRect.bottom - 2));
            this.m_occupiedBoundingRect.x = (_local8 * this.m_gridDelta);
            this.m_occupiedBoundingRect.y = (_local10 * this.m_gridDelta);
            this.m_occupiedBoundingRect.width = (((_local9 - _local8) + 1) * this.m_gridDelta);
            this.m_occupiedBoundingRect.height = (((_local11 - _local10) + 1) * this.m_gridDelta);
			
			// 重新计算整个地图的边界
            this.m_boundingRect.x = (_local8 - 1);
            this.m_boundingRect.y = (_local10 - 1);
            this.m_boundingRect.width = ((_local9 - _local8) + 3);
            this.m_boundingRect.height = ((_local11 - _local10) + 3);
			
			// 把地图其他没用占用的cell标记为0
            _local7 = this.m_boundingRect.x;
            while (_local7 < this.m_boundingRect.right) {
                if (this.m_cells[_local7] == null){
                    this.m_cells[_local7] = new Array();
                };
                _local13 = this.m_boundingRect.y;
                while (_local13 < this.m_boundingRect.bottom) {
                    if (this.m_cells[_local7][_local13] == null){
                        this.m_cells[_local7][_local13] = 0;
                    };
                    _local13++;
                };
                _local7++;
            };
        }
        public function pointInTerritory(_arg1:int, _arg2:int):Boolean{
            var _local3:Boolean;
            var _local4:int = (this.m_boundingRect.x + Math.floor(((_arg1 / this.m_gridDelta) - this.m_boundingRect.x)));
            var _local5:int = (this.m_boundingRect.y + Math.floor(((_arg2 / this.m_gridDelta) - this.m_boundingRect.y)));
            if ((((((_local4 >= this.m_boundingRect.x)) && ((_local4 < this.m_boundingRect.right)))) && ((((_local5 >= this.m_boundingRect.y)) && ((_local5 < this.m_boundingRect.bottom)))))){
                _local3 = this.m_cells[_local4][_local5];
            };
            return (_local3);
        }
        public function rectInTerritory(_arg1:Rectangle):Boolean{
            var _local4:int;
            var _local2:Boolean;
            var _local3:int = _arg1.x;
            while (((_local2) && ((_local3 < _arg1.right)))) {
                _local4 = _arg1.y;
                while (((_local2) && ((_local4 < _arg1.bottom)))) {
                    _local2 = this.pointInTerritory(_local3, _local4);
                    _local4++;
                };
                _local3++;
            };
            return (_local2);
        }
        protected function validCell(_arg1:int, _arg2:int):Boolean{
            return ((((((_arg1 >= this.m_boundingRect.x)) && ((_arg1 < this.m_boundingRect.right)))) && ((((_arg2 >= this.m_boundingRect.y)) && ((_arg2 < this.m_boundingRect.bottom))))));
        }
        protected function cellOccupied(_arg1:int, _arg2:int):Boolean{
            var _local3:Boolean;
            if (this.validCell(_arg1, _arg2)){
                _local3 = this.m_cells[_arg1][_arg2];
            };
            return (_local3);
        }
		
		// 判断这个cell周围的cell是不是被标记成1了
        protected function cellHasOccupiedNeighbor(_arg1:int, _arg2:int):Boolean{
            var _local4:Point;
            var _local5:int;
            var _local6:int;
            var _local3:Boolean;
            for each (_local4 in this.m_surroundingCellOffsets) {
                _local5 = (_arg1 + _local4.x);
                _local6 = (_arg2 + _local4.y);
                if (((this.validCell(_local5, _local6)) && (this.m_cells[_local5][_local6]))){
                    _local3 = true;
                    break;
                };
            };
            return (_local3);
        }
        public function getClosestExpansionRect(_arg1:Vector2):Rectangle{
            var _local2:Rectangle;
            var _local3:int = (this.m_boundingRect.x + Math.floor(((_arg1.x / this.m_gridDelta) - this.m_boundingRect.x)));
            var _local4:int = (this.m_boundingRect.y + Math.floor(((_arg1.y / this.m_gridDelta) - this.m_boundingRect.y)));
            _local3 = MathUtil.clamp(_local3, this.m_boundingRect.x, (this.m_boundingRect.right - 1));
            _local4 = MathUtil.clamp(_local4, this.m_boundingRect.y, (this.m_boundingRect.bottom - 1));
            _local2 = new Rectangle((_local3 * this.m_gridDelta), (_local4 * this.m_gridDelta), this.m_gridDelta, this.m_gridDelta);
            return (_local2);
        }
        public function getClosestAdjacentRect(_arg1:Vector2):Rectangle{
            var _local2:Rectangle;
            var _local5:int;
            var _local6:int;
            var _local7:int;
            var _local8:int;
            var _local9:int;
            var _local10:int;
            var _local11:int;
            var _local12:int;
            var _local3:int = (this.m_boundingRect.x + Math.floor(((_arg1.x / this.m_gridDelta) - this.m_boundingRect.x)));
            var _local4:int = (this.m_boundingRect.y + Math.floor(((_arg1.y / this.m_gridDelta) - this.m_boundingRect.y)));
            _local3 = MathUtil.clamp(_local3, this.m_boundingRect.x, (this.m_boundingRect.right - 1));
            _local4 = MathUtil.clamp(_local4, this.m_boundingRect.y, (this.m_boundingRect.bottom - 1));
            if ((((this.m_cells[_local3][_local4] == 0)) && (this.cellHasOccupiedNeighbor(_local3, _local4)))){
                _local2 = new Rectangle((_local3 * this.m_gridDelta), (_local4 * this.m_gridDelta), this.m_gridDelta, this.m_gridDelta);
            } else {
                _local5 = 99999;
                _local8 = -1;
                _local9 = -1;
                _local10 = this.m_boundingRect.x;
                while (_local10 < this.m_boundingRect.right) {
                    _local11 = this.m_boundingRect.y;
                    while (_local11 < this.m_boundingRect.bottom) {
                        if ((((this.m_cells[_local10][_local11] == 0)) && (this.cellHasOccupiedNeighbor(_local10, _local11)))){
                            _local6 = (_local10 - _local3);
                            _local7 = (_local11 - _local4);
                            _local12 = ((_local6 * _local6) + (_local7 * _local7));
                            if (_local12 < _local5){
                                _local5 = _local12;
                                _local8 = _local10;
                                _local9 = _local11;
                            };
                        };
                        _local11++;
                    };
                    _local10++;
                };
                _local2 = new Rectangle((_local8 * this.m_gridDelta), (_local9 * this.m_gridDelta), this.m_gridDelta, this.m_gridDelta);
            };
            return (_local2);
        }
        public function get occupiedRects():Vector.<Rectangle>{
            return (this.m_occupiedRects);
        }
        public function getMapBoundary():Vector.<Point>{
            var _local3:int;
            var _local4:int;
            var _local5:int;
            var _local1:Vector.<Point> = new Vector.<Point>();
            var _local2:int = this.m_boundingRect.x;
            while (_local2 < this.m_boundingRect.right) {
                _local3 = this.m_boundingRect.y;
                while (_local3 < this.m_boundingRect.bottom) {
                    _local4 = (_local2 * this.m_gridDelta);
                    _local5 = (_local3 * this.m_gridDelta);
                    if (this.m_cells[_local2][_local3] == 1){
                        if (!this.cellOccupied((_local2 - 1), _local3)){
                            _local1.push(new Point(_local4, _local5));
                            _local1.push(new Point(_local4, (_local5 + this.m_gridDelta)));
                        };
                        if (!this.cellOccupied((_local2 + 1), _local3)){
                            _local1.push(new Point((_local4 + this.m_gridDelta), _local5));
                            _local1.push(new Point((_local4 + this.m_gridDelta), (_local5 + this.m_gridDelta)));
                        };
                        if (!this.cellOccupied(_local2, (_local3 - 1))){
                            _local1.push(new Point(_local4, _local5));
                            _local1.push(new Point((_local4 + this.m_gridDelta), _local5));
                        };
                        if (!this.cellOccupied(_local2, (_local3 + 1))){
                            _local1.push(new Point(_local4, (_local5 + this.m_gridDelta)));
                            _local1.push(new Point((_local4 + this.m_gridDelta), (_local5 + this.m_gridDelta)));
                        };
                    };
                    _local3++;
                };
                _local2++;
            };
            return (_local1);
        }

    }
}//package Classes 
